package com.example.manager.filter;

import com.example.manager.config.LoginUser;
import com.example.manager.domain.R;
import com.example.manager.domain.SysUser;
import com.example.manager.service.SysMenuService;
import com.example.manager.utils.JwtUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

//OncePerRequestFilter 是一个过滤器（spring提供的）
@Component
public class TokenFilter extends OncePerRequestFilter {
    private static List<String> whiteList = Arrays.asList(
            "/submitLogin",
            "/register");

    @Value("${spring.profiles.active}")
    private String active;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private SysMenuService menusService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String method = request.getMethod();
        if (method.equals("OPTIONS")) {
            //继续往下执行....
            filterChain.doFilter(request, response);
            return;
        }
        if(active.equals("dev")){//开发者模式
            SysUser users = new SysUser();
            users.setUserId(1);
            users.setUsername("admin");
            LoginUser user = new LoginUser(users,menusService.findSysMenus());
            UsernamePasswordAuthenticationToken authenticationToken
                    = new UsernamePasswordAuthenticationToken(
                    "admin",
                    null,
                    user.getAuthorities());
            request.setAttribute("user", user.getUsers());
            //将通知给security，我已经验证了token你就不需要验证了
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            //继续往下执行....
            filterChain.doFilter(request, response);
            return;
        }
        if (whiteList.contains(request.getRequestURI())) {
            //继续往下执行....
            filterChain.doFilter(request, response);
            return;
        }
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setContentType("application/json;charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        String token = request.getHeader("token");//从请求的头部获取token
        System.out.println("获取到Token:" + token);
        System.out.println("请求地址：" + request.getRequestURI());
        System.out.println("请求类型：" + request.getMethod());
        //验证是否有token
        if (token == null) {
            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writeValueAsString(R.fail(401, "你还未登录"));
            response.getWriter().write(json);
        } else {
            //验证token是否已经过期
            if (JwtUtils.isExpired(token)) {
                ObjectMapper mapper = new ObjectMapper();
                String json = mapper.writeValueAsString(R.fail(401, "你登录已经过期，请重新登录"));
                response.getWriter().write(json);
            } else {
                String username = JwtUtils.getUsername(token);
                //从redis中获取到用户信息和菜单信息（权限信息）
                LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get("login:" + username);
                if (loginUser == null) {
                    ObjectMapper mapper = new ObjectMapper();
                    String json = mapper.writeValueAsString(R.fail(401, "你被强制下线了，请重新登录"));
                    response.getWriter().write(json);
                } else {
                    UsernamePasswordAuthenticationToken authenticationToken
                            = new UsernamePasswordAuthenticationToken(
                            username,
                            null,
                            loginUser.getAuthorities());
                    request.setAttribute("user", loginUser.getUsers());
                    //将通知给security，我已经验证了token你就不需要验证了
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    //上面验证都通过了，我就可以进去服务器
                    filterChain.doFilter(request, response);
                }
            }
        }
    }
}